package com.jdbc.util;

import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 一个检查为null的特殊用法：
 * StringUtil.isNullOrEmpty(mi.getParent()) ? "-1" : mi.getParent().getId()
 * @author huzhe
 *
 */
public class StringUtil {
	
	/**
	 * 判断字符串 是否为null 或 空串。
	 * @param str
	 * @return
	 */
	public static boolean isNullOrEmpty(String str){
		return (str == null || str.equals(""));
	}
	/**
	 * 判断 Collection 是否为null 或 空（没有一个元素）
	 * @param coll
	 * @return
	 */
	public static boolean isNullOrEmpty(@SuppressWarnings("rawtypes")Collection coll){
		return (coll == null || coll.size()==0);
	}
	/**
	 * 判断Map 是否为null 或 空（没有一个元素）
	 * @param map
	 * @return
	 */
	public static boolean isNullOrEmpty(@SuppressWarnings("rawtypes")Map map){
		return (map == null || map.size()==0);
	}
	/**
	 * 判断 数组 是否为null 或 空（没有一个元素）
	 * @param objs
	 * @return
	 */
	public static boolean isNullOrEmpty(Object[] objs){
		return (objs == null || objs.length==0);
	}
	/**
	 * 判断Object是否为null，字符串类型还会判断是否为空串。
	 * @param o
	 * @return
	 */
	public static boolean isNullOrEmpty(Object o) {
		if(o == null){ return true;}
		else if( o instanceof String){
			return isNullOrEmpty(o.toString());
		}
		else{
			return false;
		}
	}
	/**
	 * 
	 * 将null转换为空串（""） ，非空的返回原值。
	 * @param str 被检查字符串
	 * @return
	 */
	public static String filterNullToEmpty(String str){
		return ( str == null ) ? "" : str;
	}
	/**
	 * 调用参数的toString方法，参数为null将返回空串。当参数为String类型推荐使用 {@link StringUtil#filterNullToEmpty(String str)}方法
	 * @param str
	 * @return
	 */
	public static String toStringNullToEmpty(Object str){
		return ( str == null ) ? "" : str.toString();
	}
	
	/**
	 * 将参数指定的字符串转换为uuid，如果转换失败返回null.
	 * @param value 
	 * @return
	 */
	public static UUID toUUID(Object value){
		String v = toStringNullToEmpty(value);
		UUID uuid = null;
		try{
			uuid = UUID.fromString(v);
		}
		catch (Exception e) {}
		return uuid;
	}
	/**
	 * 返回空的uuid(00000000-0000-0000-0000-000000000000)
	 * @return
	 */
	public static UUID emptyUUID(){
		return UUID.fromString("00000000-0000-0000-0000-000000000000");
	}
	/**
	 * 判断参数能不能转换成一个有效的uuid值.
	 * @param value
	 * @return
	 */
	public static boolean isValidUUID(Object value){
		UUID uuid = toUUID(value);
		if( uuid != null &&   (!emptyUUID().equals(uuid))){
			return true;
		}
		else{
			return false;
		}
	}
	
	
	
	
	/**
	 * 将字符串解析为指定的类型，如果解析失败返回指定类型的默认值（Integer[0],Double[0.0]）
	 * @param value value.toString()参与解析，如果为null则使用空串("")参与解析
	 * @param t  支持：Integer(int)、Long(long)、Double(double)
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T parseToNumber(Object value,Class<T> t){
		if(t == Integer.class || t == int.class ){
			
			return (T)parseToNumber(value, Integer.class, 0);
		}
		else if(t == Long.class || t == long.class ){
			return (T)parseToNumber(value, Long.class, 0L);
		}
		else if(Double.class==t|| double.class == t){
			return (T)parseToNumber(value, Double.class, 0.0);
		}
		return null;
	}
	/**
	 * 将字符串解析为指定的类型，如果解析失败返回指定类型的默认值
	 * @param value value.toString()参与解析，如果为null则使用空串("")参与解析
	 * @param t  支持：Integer(int)、Long(long)、Double(double)；<br/>
	 *          int,long 遇到 null、""(空串)、数字以外字符(除了负号，例如-1)会抛出NumberFormatException，
	 *          double允许例如：0.128、.128、128，以及合适位置使用Ee、Ff、Dd、负号-；遇到null、""(空串)、其他非法字符会抛异常。 
	 * @param def 解析失败后的默认值。
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T parseToNumber(Object value,Class<T> t, T def){
		if(t == Integer.class || t == int.class ){
			try {
				return (T)Integer.valueOf(value== null ? "": value.toString());
			} catch (NumberFormatException e) {
				return def;
			}
		}
		else if(t == Long.class || t == long.class ){
			try {
				return (T)Long.valueOf(value== null ? "": value.toString());
			} catch (NumberFormatException e) {
				return def;
			}
		}
		
		else if(Double.class==t|| double.class == t){
			try {
				return (T)Double.valueOf(value== null ? "": value.toString());
			} catch (NumberFormatException e) {
				return def;
			}
		}
		return null;
	}
	/** yyyy/MM/dd HH:mm:ss */
	private static SimpleDateFormat fullDatetimeSlash = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
	/** yyyy/MM/dd */
	private static SimpleDateFormat fullDateSlash = new SimpleDateFormat("yyyy/MM/dd");
	private static SimpleDateFormat fullDate = new SimpleDateFormat("yyyy-MM-dd");
	private static SimpleDateFormat fullDatetime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	/**
	 * <b>有可能返回null，请判断返回值。</b>
	 * @param value 格式为yyyy-MM-dd 的字符串，否则返回null。
	 * @return
	 */
	public static Date parseToDate(Object value){
		Date date = null;
		try {
			synchronized (fullDate) {
				date = fullDate.parse(toStringNullToEmpty(value));
			}
		} catch (ParseException e) { }
		return date;
	}
	/**
	 * <b>有可能返回null，请判断返回值。</b>
	 * @param value 格式为yyyy/MM/dd 的字符串，否则返回null。
	 * @return
	 */
	public static Date parseToDateWithSlash(Object value){
		Date date = null;
		try {
			synchronized (fullDateSlash) {
				date = fullDateSlash.parse(toStringNullToEmpty(value));
			}
		} catch (ParseException e) { }
		return date;
	}
	/**
	 * 返回"yyyy-MM-dd"格式字符串。如果传入null，返回""空字符串。
	 * @param value 如果传入null，返回""空字符串。
	 * @return
	 */
	public static String toDateString(Date value){
		String date = "";
		if(value != null){
			synchronized (fullDate) {
				date = fullDate.format(value);
			}
		}
		return date;
	}
	/**
	 * 返回"yyyy/MM/dd"格式字符串。如果传入null，返回""空字符串。
	 * @param value 如果传入null，返回""空字符串。
	 * @return
	 */
	public static String toDateStringWithSlash(Date value){
		String date = "";
		if(value != null){
			synchronized (fullDateSlash) {
				date = fullDateSlash.format(value);
			}
		}
		return date;
	}
	
	/**
	 * <b>有可能返回null，请判断返回值。</b>
	 * @param value 格式为yyyy-MM-dd HH:mm:ss的字符串，否则返回null。
	 * @return
	 */
	public static Date parseToDateTime(Object value){
		Date date = null;
		try {
			synchronized (fullDatetime) {
				date = fullDatetime.parse(toStringNullToEmpty(value));
			}
		} catch (ParseException e) { }
		return date;
	}
	/**
	 * <b>有可能返回null，请判断返回值。</b>
	 * @param value 格式为yyyy/MM/dd HH:mm:ss 的字符串，否则返回null。
	 * @return
	 */
	public static Date parseToDateTimeWithSlash(Object value){
		Date date = null;
		try {
			synchronized (fullDatetimeSlash) {
				date = fullDatetimeSlash.parse(toStringNullToEmpty(value));
			}
		} catch (ParseException e) { }
		return date;
	}
	/**
	 * 返回"yyyy-MM-dd HH:mm:ss"格式字符串。如果传入null，返回""空字符串。
	 * @param value 如果传入null，返回""空字符串。
	 * @return
	 */
	public static String toDateTimeString(Date value){
		String date = "";
		if(value != null){
			synchronized (fullDatetime) {
				date = fullDatetime.format(value);
			}
		}
		return date;
	}
	/**
	 * 返回"yyyy/MM/dd HH:mm:ss"格式字符串。如果传入null，返回""空字符串。
	 * @param value 如果传入null，返回""空字符串。
	 * @return
	 */
	public static String toDateTimeStringWithSlash(Date value){
		String date = "";
		if(value != null){
			synchronized (fullDatetimeSlash) {
				date = fullDatetimeSlash.format(value);
			}
		}
		return date;
	}
	
	
	public static long lengthGBK(String value){
		value = StringUtil.filterNullToEmpty(value);
		try {
			return value.getBytes("GBK").length;
		} catch (UnsupportedEncodingException e) {
		}
		return 0;
	}
	
	/** "abcde.x.acb.xddd", ".x" ->"abcde"[.x] */
	public static String cutLeft(String str, String keyString, boolean includeKey){
		String result = "";
		if(str != null && keyString != null){
			int index = str.indexOf(keyString);
			if(includeKey){
				result = str.substring(0, index+keyString.length());
			}
			else{
				result = str.substring(0, index);
			}
		}
		return result;
	}
	/** "abcde.x.acb.xddd", ".x" ->[.x]".acb.xddd" */
	public static String cutRight(String str, String keyString, boolean includeKey){
		String result = "";
		if(str != null && keyString != null){
			int index = str.indexOf(keyString);
			if(!includeKey){
				result = str.substring(index+keyString.length(), str.length());
			}
			else{
				result = str.substring(index, str.length());
			}
		}
		return result;
	}
	/** "abcde.x.acb.xddd", ".x" ->"abcde.x.acb"[.x] */
	public static String cutLeftLast(String str, String keyString, boolean includeKey){
		String result = "";
		if(str != null && keyString != null){
			int index = str.lastIndexOf(keyString);
			if(includeKey){
				result = str.substring(0, index+keyString.length());
			}
			else{
				result = str.substring(0, index);
			}
		}
		return result;
	}
	/** "abcde.x.acb.xddd", ".x" ->[.x]"ddd" */
	public static String cutRightLast(String str, String keyString, boolean includeKey){
		String result = "";
		if(str != null && keyString != null){
			int index = str.lastIndexOf(keyString);
			if(!includeKey){
				result = str.substring(index+keyString.length(), str.length());
			}
			else{
				result = str.substring(index, str.length());
			}
		}
		return result;
	}
	
	public static String substringGBK(String value,int len){
		String vstr = StringUtil.filterNullToEmpty(value);
		int i = len;
		if(vstr.length()<i){
			i = vstr.length();
		}
		while(StringUtil.lengthGBK(vstr)>len){
			try{
				i--;
				vstr = vstr.substring(0, i);
			}catch (Exception e) {
				System.err.println("处理值："+vstr);
				e.printStackTrace();
			}
			
		}
		return vstr;
	}
	
	/** 左侧填充指定字符串
	 * 
	 * @param str  被填充字符串
	 * @param resultLen  最终长度
	 * @param padChar  用来填充的字符。
	 * @return
	 */
	public static String leftPad(String str,int resultLen,char padChar){
		StringBuilder sb = new StringBuilder(filterNullToEmpty(str));
		while(sb.length() < resultLen){
			sb.insert(0, padChar);
		}
		return sb.toString();
	}
	/**
	 * 是否为xml定义的非法字符。
	 * @param c
	 * @return
	 */
	public static boolean isXmlInvalidChar(char c){
		if(        (c == 0x9)
                || (c == 0xA) 
                || (c == 0xD) 
                || ((c >= 0x20) && (c <= 0xD7FF)) 
                || ((c >= 0xE000) && (c <= 0xFFFD)) 
                || ((c >= 0x10000) && (c <= 0x10FFFF))){
            return true;
        } else {
            return false;
        }
	}
	/**
	 * 过滤掉非法的xml字符
	 * @param data
	 * @return
	 */
	public static String filterXmlInvalidChar(String data){
		data = filterNullToEmpty(data);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < data.length(); i++) {
			char ch = data.charAt(i);
			if(!isXmlInvalidChar(ch)) {
				sb.append(ch);
			}
		}
		return sb.toString();
	}
	
	/**
	 * 将字符串str[第一个参数]根据分隔符delimiter[第二个参数] 分割成固定个数len[第三个参数]. 每个元素都不为null。
	 * @param str 被分割的字符串，不用担心是null。
	 * @param delimiter 分隔符, 注意 正则表达式的关键字。
	 * @param len 正数-执行固定个数，0-返回实际被分割结果。
	 * @return 不会返回 null
	 */
	public static String[] split(Object str, String delimiter, int len){
		String[] locations = StringUtil.toStringNullToEmpty(str).split(delimiter);
		int olen = locations.length;
		if(len >0){
			String[] result = new String[len];
			for(int i=0; i<len; i++){
				if(i>=olen){ result[i] = ""; }
				else{ result[i] = locations[i]; }
			}
			return result;
		}
		else{
			return locations!=null ? locations : NothingStrArray;
		}
	}
	/**
	 * 将字符串str[第一个参数]根据分隔符delimiter[第二个参数] 分割成 元素集合，剔除null，空串，trim后为空的。
	 *
	 * @param str 被分割的字符串，不用担心是null。
	 * @param delimiter 分隔符, 注意 正则表达式的关键字。
	 */
	public static List<String> splitTrim(Object str, String delimiter){
		String[] locations = StringUtil.toStringNullToEmpty(str).split(delimiter);
		List<String> result = new ArrayList<String>();
		for(String l : locations){
			String lt = StringUtil.filterNullToEmpty(l).trim();
			if(!StringUtil.isNullOrEmpty(lt)){
				result.add(lt);
			}
		}
		return result;
	}
	/**
	 * 将字符串str[第一个参数]根据分隔符delimiter[第二个参数] 分割成 数组，剔除null，空串，trim后为空的。
	 * @param str
	 * @param delimiter
	 * @return
	 */
	public static String[] splitTrim2(Object str, String delimiter){
		List<String> result = splitTrim(str, delimiter);
		return result.toArray(NothingStrArray);
	}
	
	public static final String[] NothingStrArray = new String[0];
}

